/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is Forte for Java, Community Edition. The Initial * Developer of the Original Code is Sun Microsystems, Inc. Portions * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved. */ package org.netbeans.modules.debugger.jpda; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import com.sun.jdi.Value; import com.sun.jdi.Field; import com.sun.jdi.ThreadReference; import com.sun.jdi.ArrayReference; import com.sun.jdi.ObjectReference; import com.sun.jdi.StackFrame; import com.sun.jdi.ReferenceType; import com.sun.jdi.ObjectCollectedException; import com.sun.jdi.InvalidStackFrameException; import com.sun.jdi.ClassNotPreparedException; import com.sun.jdi.IncompatibleThreadStateException; import com.sun.tools.example.debug.expr.ExpressionParser; import com.sun.tools.example.debug.expr.ParseException; import org.openide.debugger.Watch; import org.openide.util.NbBundle; import org.netbeans.modules.debugger.support.AbstractVariable; import org.netbeans.modules.debugger.support.AbstractWatch; import org.netbeans.modules.debugger.support.AbstractThread; import org.netbeans.modules.debugger.support.PrintAction; import org.netbeans.modules.debugger.support.util.Validator; import org.netbeans.modules.debugger.support.util.Protector; /** * Standart implementation of Watch interface. * @see org.openide.debugger.Watch * * @author Jan Jancura * @version 0.18, Feb 23, 1998 */ public class JPDAWatch extends AbstractWatch { /** generated Serialized Version UID */ static final long serialVersionUID = 3439367144447814302L; // private variables ..................................................... private JPDAVariable var; protected transient PropertyChangeSupport pcs; protected transient Validator validator; protected transient boolean inScope = false; /** Name of watch like xxx.yyy [2]. */ protected String displayName; // init ..................................................................... /** * Non public constructor called from the JavaDebugger only. * User must create watch from Debugger.getNewWatch () method. */ JPDAWatch (JPDADebugger debugger) { var = new JPDAVariable (debugger, false); validator = debugger.getValidator (); init (); } private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException { in.defaultReadObject (); validator = var.getDebugger().getValidator (); init (); } protected void init () { if (validator != null) validator.add (this); pcs = new PropertyChangeSupport (this); } // AbstractWatch implementation ......................................................... /** * Returns the name of this watch. * * @return the name of this watch. */ public String getVariableName () { return displayName; } /** * Destroys the watch. Removes it from the list of all watches in the system. */ public void remove () { var.getDebugger().removeWatch (this); } /** * Sets variable name of this watch. * * @param name The name of variable of this watch. */ public void setVariableName (String displayName) { String old = this.displayName; this.displayName = displayName; validate (); } /** Getter to test if the property is "hidden". If a property is hidden it * is not presented in the list of all properties. Such a property can be used * for private usage of the IDE, not displaying anything to user. * <P> * To create hidden watch, use <CODE>Debugger.createWatch ("name", true)</CODE> method. * * @return true if the watch is hidden, false otherwise */ public boolean isHidden () { Watch[] w = var.getDebugger().getWatches (); int i, k = w.length; for (i = 0; i < k; i++) if (w [i] == this) return false; return true; } // other methods ...................................................................... /** * Returns true if this variable is in scope. * * @return true if this variable is in scope. */ public boolean isInScope () { return (getErrorMessage () == null); // return inScope; } /** * Create AbstractVariable object for this Watch. Can return null, if this Watch currently not * represents valide variable. * * @return AbstractVariable object for this class. */ public AbstractVariable getVariable () { return (AbstractVariable) clone (); } /** * Returns true if this variable hasn't any fields. * * @return True if this variable hasn't any fields. */ public boolean isLeaf () { return false; } public boolean equals (java.lang.Object o) { return hashCode () == o.hashCode (); } public int hashCode () { return System.identityHashCode (this); } /** * Checks value of this watch and if is valide, and sets it. */ public void validate () { //S ystem.out.println ("JPDAWatch.validate " + getVariableName () + " : " + // NOI18N //debugger + " : " + var.getDebugger().getState ()); // NOI18N if (var.getDebugger().getState () == var.getDebugger().DEBUGGER_NOT_RUNNING ) { setError (NbBundle.getBundle (JPDAWatch.class).getString ("EXC_No_session")); pcs.firePropertyChange (null, null, null); } else if (var.getDebugger().getState () != var.getDebugger().DEBUGGER_STOPPED) { setError (NbBundle.getBundle (JPDAWatch.class).getString ("CTL_No_context")); pcs.firePropertyChange (null, null, null); } else { final JPDAThread tt = (JPDAThread) var.getDebugger().getCurrentThread (); if (tt != null) { refreshValue (tt); } else { setError (NbBundle.getBundle (JPDAWatch.class).getString ("CTL_No_context")); pcs.firePropertyChange (null, null, null); } } } /** * @return true if debugger is stopped. */ public boolean canValidate () { int state = var.getDebugger().getState (); return (state == JPDADebugger.DEBUGGER_STOPPED) || (state == JPDADebugger.DEBUGGER_NOT_RUNNING); } /** * @return false, watch cannot be removed from validator when debugger is finished */ public boolean canRemove () { return false; } /** * Refresh value of watch in given context. */ void refreshValue (final JPDAThread tt) { ThreadReference rt = tt.getThreadReference (); final StackFrame sf; try { sf = rt.frame (0); } catch (Exception e) { setError (NbBundle.getBundle (JPDAWatch.class).getString ("CTL_No_context")); pcs.firePropertyChange (null, null, null); return; } var.setErrorMessage (null); Value v; try { //S ystem.out.println ("EXPRESSION ENTER " + displayName); // NOI18N v = (Value) new Protector ("ExpressionParser") { // NOI18N public Object protect () throws Exception { //S ystem.out.println ("EXPRESSION ENTER1 " + displayName); // NOI18N Value vv = ExpressionParser.evaluate ( displayName, var.getDebugger().virtualMachine, new ExpressionParser.GetFrame () { public StackFrame get () { return sf; } } ); //S ystem.out.println ("EXPRESSION EXIT1 " + displayName); // NOI18N return vv; } }.throwAndWait (null); //S ystem.out.println ("EXPRESSION EXIT " + displayName); // NOI18N } catch (ParseException e) { //S ystem.out.println ("EXPRESSION EXIT " + displayName); // NOI18N // a pacth for static variables ******************************************* v = null; boolean found = false; try { ReferenceType refType = sf.thisObject ().referenceType (); v = refType.getValue (refType.fieldByName (displayName)); found = true; } catch (ObjectCollectedException ee) {} catch (InvalidStackFrameException ee) {} catch (ClassNotPreparedException ee) {} catch (java.lang.IllegalArgumentException ee) {} catch (NullPointerException ee) {} if (!found) { setError (e.getMessage ()); pcs.firePropertyChange (null, null, null); return; } // end of patch *********************************************************** } catch (ThreadDeath e) { //S ystem.out.println ("EXPRESSION EXIT " + displayName); // NOI18N setError ("Deadlock detected while resolving expression."); // NOI18N pcs.firePropertyChange (null, null, null); return; } catch (Throwable e) { //S ystem.out.println ("EXPRESSION EXIT " + displayName); // NOI18N setError (e.toString ()); pcs.firePropertyChange (null, null, null); return; } if (v == null) setNull (); // really null value? else update ( displayName, v, v.type ().name () ); pcs.firePropertyChange (null, null, null); } public void refresh (AbstractThread t) { refreshValue ((JPDAThread)t); } public synchronized void addPropertyChangeListener (PropertyChangeListener listener) { pcs.addPropertyChangeListener (listener); } public synchronized void removePropertyChangeListener (PropertyChangeListener listener) { pcs.removePropertyChangeListener (listener); } protected void firePropertyChange (String s, Object o, Object n) { pcs.firePropertyChange (s, o, n); } // Delegating methods for JPDAVariable instance .................................. // Methods from JPDAVariable public void setAsText (final String value) { var.setAsText (value); } public AbstractVariable[] getFields () { return var.getFields (); } boolean update (String name, ArrayReference array, int index, String type) { return var.update (name, array, index, type); } boolean update (Field field, ObjectReference parentObject) { return var.update (field, parentObject); } void update (String name, Value remoteValue, String type) { var.update (name, remoteValue, type); } void setNull () { var.setNull (); } void setValue (String v) { var.setValue (v); } protected void setError (String description) { var.setError_protected (description); } // methods from VariableImpl protected java.lang.Object clone () { return var.clone_protected (); } public String getAsText () { return var.getAsText (); } public String getType () { return var.getType (); } public String getInnerType () { return var.getInnerType (); } public boolean isObject () { return var.isObject (); } public boolean isArray () { return var.isArray (); } public String getModifiers () { return var.getModifiers (); } public String getErrorMessage () { return var.getErrorMessage (); } public String toString () { return var.toString (); } } /* * Log * 13 Gandalf-post-FCS1.11.4.0 3/28/00 Daniel Prusa * 12 Gandalf 1.11 1/14/00 Daniel Prusa NOI18N * 11 Gandalf 1.10 1/13/00 Daniel Prusa NOI18N * 10 Gandalf 1.9 12/30/99 Daniel Prusa Validator placed into * Watch * 9 Gandalf 1.8 12/21/99 Daniel Prusa Interfaces Debugger, * Watch, Breakpoint changed to abstract classes. * 8 Gandalf 1.7 12/10/99 Jan Jancura Deadlock protection for * JPDA * 7 Gandalf 1.6 11/8/99 Jan Jancura Somma classes renamed * 6 Gandalf 1.5 10/23/99 Ian Formanek NO SEMANTIC CHANGE - Sun * Microsystems Copyright in File Comment * 5 Gandalf 1.4 10/5/99 Jan Jancura Serialization of * debugger. * 4 Gandalf 1.3 9/15/99 Jan Jancura * 3 Gandalf 1.2 9/9/99 Jan Jancura * 2 Gandalf 1.1 9/3/99 Jan Jancura * 1 Gandalf 1.0 9/2/99 Jan Jancura * $ */